package com.easykoo.ioc.xml;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.easykoo.ioc.BeanFactory;
import com.easykoo.ioc.Exception.BeanWireException;
import com.easykoo.ioc.Exception.NoSuchBeanException;

public class XMLBeanFactory extends BeanFactory {
	private Log logger = LogFactory.getLog(this.getClass());

	public static XMLBeanFactory xmlBeanFactory;

	public static Map<String, Object> entryMap;

	public static XMLBeanFactory getInstance() {
		if (xmlBeanFactory == null) {
			xmlBeanFactory = new XMLBeanFactory();
		}
		if (entryMap == null) {
			entryMap = new HashMap<String, Object>();
		}
		return xmlBeanFactory;
	}

	private XMLBeanFactory() {
	}

	public void push(Map<String, Object> map) {
		entryMap.putAll(map);
	}

	public Map<String, Object> getEntryMap() {
		return entryMap;
	}

	public Object getBean(String beanName) throws NoSuchBeanException,
			BeanWireException {
		try {
			if (entryMap.containsKey(beanName)) {
				Entry bean = (Entry) entryMap.get(beanName);

				Object beanObject = null;
				beanObject = Class.forName(bean.getClazz()).newInstance();
				if (bean.getAutowire() == null
						|| !"byName".equalsIgnoreCase(bean.getAutowire())) {
					List<Property> properties = bean.getProperties();
					if (properties != null) {
						for (Property property : properties) {
							String methodName = "set"
									+ property.getName().substring(0, 1)
											.toUpperCase()
									+ property.getName().substring(1);
							Object targetObject = getBean(property.getRefId());
							Method method = beanObject.getClass().getMethod(
									methodName,
									targetObject.getClass().getInterfaces()[0]);
							method.invoke(beanObject, targetObject);
						}
					}
				} else if (bean.getAutowire() != null
						&& "byName".equalsIgnoreCase(bean.getAutowire())) {
					return super.getBeanByName(bean);
				} else {
					// TODO
				}
				return beanObject;
			} else {
				throw new NoSuchBeanException(beanName);
			}
		} catch (InstantiationException e) {
			throw new BeanWireException(e);
		} catch (IllegalAccessException e) {
			throw new BeanWireException(e);
		} catch (ClassNotFoundException e) {
			throw new BeanWireException(e);
		} catch (NoSuchMethodException e) {
			throw new BeanWireException(e);
		} catch (InvocationTargetException e) {
			throw new BeanWireException(e);
		}
	}

}
